home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / usenet / sources / volume89 / kernel / setcpu14.1 < prev    next >
Internet Message Format  |  1989-03-15  |  53KB

  1. Path: xanth!nic.MR.NET!hal!cwjcc!mailrus!ulowell!page
  2. From: page@swan.ulowell.edu (Bob Page)
  3. Newsgroups: comp.sources.amiga
  4. Subject: v89i057:  setcpu - show/set cpu attributes v1.4
  5. Message-ID: <12239@swan.ulowell.edu>
  6. Date: 15 Mar 89 18:50:50 GMT
  7. Organization: University of Lowell, Computer Science Dept.
  8. Lines: 1415
  9. Approved: page@swan.ulowell.edu
  10.  
  11. Submitted-by: cbmvax!daveh (Dave Haynie)
  12. Posting-number: Volume 89, Issue 57
  13. Archive-name: kernel/setcpu14.1
  14.  
  15. As well as fixing and extending the CHECK code, SetCPU V1.4 also has
  16. some simple "FASTROM" code to allow 32 bit systems with MMUs to copy
  17. ROM into RAM and then relocate this RAM as ROM, thus greatly enhancing
  18. the speed of ROM based operations.
  19.  
  20. [uuencoded executables included.  ..Bob]
  21.  
  22. #    This is a shell archive.
  23. #    Remove everything above and including the cut line.
  24. #    Then run the rest of the file through sh.
  25. #----cut here-----cut here-----cut here-----cut here----#
  26. #!/bin/sh
  27. # shar:    Shell Archiver
  28. #    Run the following text with /bin/sh to create:
  29. #    SetCPU.txt
  30. #    ROMBash.c
  31. #    SetCPU.c
  32. #    030Stuff.a
  33. #    makefile
  34. #    RomBash.uu
  35. #    SetCPU.uu
  36. # This archive created: Wed Mar 15 13:44:12 1989
  37. cat << \SHAR_EOF > SetCPU.txt
  38.  
  39.             SetCPU V1.4
  40.                by Dave Haynie 
  41.         (released to the public domain)
  42.  
  43.  
  44.     This program is designed to allow the user to detect and modify
  45. various parameters related to 32 bit CPUs in Amiga computers.  This program
  46. began life as "WhatCPU", which did little more than read the proper place
  47. in ExecBase and report what kind of CPU/FPU was in the system.  The first
  48. version of SetCPU added the capability to identify a 68030 and to change the 
  49. cache parameters of the 68020 and 68030 systems.  The recently released SetCPU
  50. V1.3 also did tests for 68882 vs. 68881, and for the presence of an MMU.  It
  51. was supposed to allow for checking of a particular thing in a startup 
  52. sequence, but unfortunately the CHECK code in V1.3 was broken.
  53.  
  54.     That brings us up to V1.4.  As well as fixing and extending the CHECK
  55. code, SetCPU V1.4 also has some simple MMU code to allow 32 bit systems with
  56. MMUs to copy ROM into RAM and then relocate this RAM as ROM, thus greatly
  57. enhancing the speed of ROM based operations.  This "FASTROM" code isn't
  58. extremely sophisticated, and could possibly run into trouble on other 32 bit
  59. systems, but it has been tested on the A2620.  It will certainly have to be 
  60. rethought to work properly with memory outside of the 68000 compatible 24 bit
  61. address space.
  62.  
  63.     In any case, the syntax of the program is given as follows:
  64.  
  65.         SetCPU [INST|DATA] [[NO]CACHE|[NO]BURST]
  66.                [[NO]FASTROM [TRAP]] [NOMMUTEST]
  67.                [CHECK 680x0|68851|6888x|MMU|FPU]
  68.  
  69. where "[]" indicates an optional parameter, "|" indicates a choice of
  70. parameters.  Typing "SetCPU ?" will retrieve this same syntax diagram.
  71. Typing SetCPU alone will result in the SYSTEM configuration being 
  72. send to the console, my current system returns this:
  73.  
  74.     SYSTEM: 68020 68881 68851 FASTROM (INST: CACHE)
  75.  
  76. This indicates I have a 68020/68881/68851 system (eg, standard A2620), I've
  77. previously installed the FASTROM translation, and my instruction cache is
  78. turned on (done by AmigaOS V1.2 or V1.3).  Note that any parameters that
  79. don't make sense to the real system configuration, such as asking to modify
  80. the data cache on a 68020 system or install the FASTROM translation on a
  81. 68000 system are just ignored.
  82.  
  83.     The individual commands are given below in detail:
  84.  
  85.  
  86. [NO]CACHE
  87.     This command will switch on or off 68020 and 68030 caches.  If
  88.     not qualified, it'll act on both instruction and data caches of
  89.     the 68030.
  90.  
  91. [NO]BURST
  92.     This command will switch on or off the burst cache line fill 
  93.     request of the 68030.  If not qualified, it'll act on both 
  94.     instruction and data caches.
  95.  
  96. INST
  97.     This preceeds a CACHE or BURST operation to restrict it's application
  98.     to the instruction cache only.
  99.  
  100. DATA
  101.     This preceeds a CACHE or BURST operation to restrict it's application
  102.     to the data cache only.
  103.  
  104. [NO]FASTROM [TRAP]
  105.     This activates the FASTROM translation on or off an MMU equipped 
  106.     system.  When switching on, it first allocates 256K of memory for
  107.     the ROM image, then currenly 512 bytes of memory for the MMU table.
  108.     It copies the ROM into the image area, then applies the translation
  109.     by pointing the MMU at the table and activating it.  The TRAP option
  110.     causes the MMU to look at all 32 bits of address; access to any 
  111.     memory outside of the 24 bit space will result in an exception, which
  112.     if unhandled, results in a GURU 2.  When TRAP is not specified, the 
  113.     MMU is only looking at 24 bits of address space.  This is the mode 
  114.     you'd normally run in.  Under V1.3 and earlier releases, a DOS bug 
  115.     can cause invalid accesses, which cause the exception, when running 
  116.     the EndCLI or NewCLI/NewShell programs; running untrapped will avoid 
  117.     gurus with these commands.  It's still possible to run into an 
  118.     exception when running without the TRAP option.  One easy way is 
  119.     writing to the ROM image, which is write protected by the MMU.  The 
  120.     NOFASTROM option will switch off the MMU and reclaim the memory used
  121.     for the ROM image and MMU table.  Note that this is achieved by 
  122.     locating these items via the appropriate MMU registers.  If any other
  123.     program set up the MMU for something, this could be a very bad thing
  124.     to do.  In general, until there's some level of OS support for the 
  125.     MMU in Amiga systems, you're really safe using only one MMU tool at 
  126.     a time.
  127.  
  128. NOMMUTEST
  129.     This option won't normally be necessary.  However, some 68020 boards
  130.     out there apparently have hardware bugs of some sort that make
  131.     testing for the MMU impossible, at least as near as I can tell.  If
  132.     your 68020 board freezes, or crashes with some kind of coprocessor 
  133.     protocol violation GURU (probably numbers $0D or $0E), you have a
  134.     problem with your 68020 board.  The most common bug is the 68020
  135.     board hardware failing to fully decode CPU space, such that the FPU
  136.     in the system also responds to the MMU's address space.
  137.  
  138. CHECK 
  139.     This option lets you check for the existence of a particular
  140.     CPU system component in a script.  It works like this:
  141.  
  142.         SetCPU CHECK 68020
  143.         If WARN
  144.             echo "No 68020 here!"
  145.         Else
  146.             echo "Sho nuff got a 68020 here!"
  147.         Endif
  148.  
  149.     The arguments to CHECK can be any of:
  150.  
  151.         68000    Matches the obvious
  152.         68010    "
  153.         68020    "
  154.         68030    "
  155.         68851    "
  156.         68881    "
  157.         68882    "
  158.         FPU    Matches 68881 or 68882
  159.         MMU    Matches 68851 or 68030
  160.  
  161. That's about it.  As mentioned, this code is public domain, and you're
  162. free to do anything with it you like.  Even make it better!  For any real
  163. MMU programming, I'd recommend both "MC68030 Enhanced 32-Bit Microprocessor
  164. User's Manual" and "MC68881 Paged Memory Management Unit User's Manual",
  165. both from Motorola.  There are some differences between the two, please make 
  166. sure, if you're writing any MMU code, that you either write code that works
  167. on both, or you specifically check for each MMU and act accordingly.
  168.  
  169. Also note that much of what SetCPU does may be wrong in a future release of
  170. the OS, so it's a very bad idea to put any of this stuff in a commercial
  171. program.  Things like identifying the MMU, CPU, or FPU that aren't fully
  172. done in 1.3 may still work in a future OS release, but if that OS is
  173. correctly identifying the MMU, CPU (eg, 68020 vs. 68030), or FPU (eg,
  174. 68881 vs. 68882), SetCPU should be using the OS's opinion of these items,
  175. not testing itself.  On a more drastic note, if an OS ever starts using
  176. the MMU, the FASTROM code will certainly break.  It's the job of the OS to
  177. arbitrate the MMU, and if the OS is doing that, no legal program would be
  178. able to come along and muck with the MMU registers without reeking havoc
  179. on the operating system.
  180.  
  181. One final note, if you have a 68020 board that locks up without the
  182. NOMMUTEST option, you'd be wise to express your concerns to the vendor
  183. of that board.  There's an awful good chance that if, in the future, 
  184. Amiga releases an operating system that knows about the MMU, it'll test
  185. for it in some way, probably similar to what I do here.  If your board
  186. locks up on MMU operations, you may not be able to run this future OS
  187. on your 68020 board.  Maybe the vendors can fix these now, instead of
  188. later when you really need this fixed.
  189.  
  190.             -Dave Haynie
  191.              PLINK:        D-Dave H
  192.              bix:        hazy
  193.              usenet:    {uunet,rutgers}!cbmvax!daveh
  194. SHAR_EOF
  195. cat << \SHAR_EOF > ROMBash.c
  196. /* This program bashes on the ROM; basically, just copying the ROM around
  197.    several times. */
  198.  
  199. #include <exec/types.h>
  200. #include <exec/nodes.h>
  201. #include <exec/lists.h>
  202. #include <exec/ports.h>
  203. #include <exec/tasks.h>
  204. #include <exec/devices.h>
  205. #include <exec/io.h>
  206. #include <devices/timer.h>
  207. #include <libraries/dos.h>
  208.  
  209. struct Task *FindTask();
  210. void SubTime(), *AllocMem();
  211. struct Device *TimerBase;
  212.  
  213. /* This routine wastes time, based on ROM access. */
  214.  
  215. #define    ROMBASE        0x00FC0000L
  216. #define ROMSIZE        0x00030000L
  217.  
  218. void ROMBash() {
  219.    short ctr;
  220.    ULONG *mem;
  221.  
  222.    mem = AllocMem(ROMSIZE,0L);
  223.    for (ctr = 0; ctr < 100; ++ctr) {
  224.       CopyMemQuick(ROMBASE,mem,ROMSIZE);
  225.    }
  226.    FreeMem(mem,ROMSIZE);
  227. }
  228.  
  229. /* This is the main program. */
  230.  
  231. void main()
  232. {
  233.    struct MsgPort port;
  234.    struct timerequest treq;
  235.    long pass;
  236.    struct timeval origtime, finaltime;
  237.  
  238.   /* Initialize the timer stuff */
  239.    port.mp_Node.ln_Name = "ROMBash";
  240.    port.mp_Flags = PA_SIGNAL;
  241.    port.mp_SigTask = FindTask(0L);
  242.    port.mp_SigBit = AllocSignal(-1L);
  243.    AddPort(&port);
  244.    treq.tr_node.io_Message.mn_ReplyPort = &port;
  245.  
  246.    if (OpenDevice(TIMERNAME,0L,&treq,0L) != 0) {
  247.       printf("Error: Can't get \"%s\"\n",TIMERNAME);
  248.       exit(20);
  249.    }
  250.    TimerBase = treq.tr_node.io_Device;
  251.    treq.tr_node.io_Command = TR_GETSYSTIME;
  252.  
  253.   /* Find the starting time */
  254.    DoIO(&treq);
  255.    origtime = treq.tr_time;
  256.  
  257.    ROMBash();
  258.  
  259.   /* Find the ending time */
  260.    DoIO(&treq);
  261.    finaltime = treq.tr_time;   
  262.  
  263.    SubTime(&finaltime,&origtime);
  264.    
  265.    printf("DONE: Elapsed time = %ld.%6ld seconds\n",
  266.           finaltime.tv_secs,finaltime.tv_micro);
  267.  
  268.    CloseDevice(&treq);
  269.    RemPort(&port);
  270.    FreeSignal((ULONG)port.mp_SigBit);
  271. }
  272. SHAR_EOF
  273. cat << \SHAR_EOF > SetCPU.c
  274. /*
  275.     SetCPU V1.4
  276.     by Dave Haynie (released to the public domain)
  277.  
  278.     MAIN PROGRAM
  279.  
  280.     V1.4
  281.     I now add several commands in the assembly stub for manipulating
  282.     a few of the MMU registers.  SetCPU now uses this to permit a
  283.     simple relocation of the ROM Kernel into 32 bit memory, which is
  284.     then translated back to the normal $00FC0000 base of the ROM
  285.     Kernel.  This will increase system performance noticably.
  286.  
  287.     V1.3
  288.     I now check for the existence of an MMU, and allow for testing of 
  289.     different CPUs, for use in CLI scripts and that kind of thing.
  290.     Apparently some 68020 boards out there don't fully decode CPU space
  291.     addresses, and, as a result, their math chip shows up in all 8
  292.     coprocessor slots.  This makes the MMU test hang, since instead of
  293.     getting no MMU, I get instead an FPU responding to an MMU 
  294.     instruction, which will probably hang the system.  The "NOMMUTEST"
  295.     option allows for the rest of this program to work on such a 
  296.     board.
  297.     
  298.     V1.2
  299.     The program now defaults to "WALLOC" mode for '030 data cache, since
  300.     that's the proper mode for Amiga data caches (user and supervisor
  301.     modes share data).
  302.     
  303.     V1.1
  304.     This program tells which Motorola CPU is in place, and allows the
  305.     some cache control on 68020 and 68030 machines.  It also sets up
  306.     the ExecBase->AttnFlags with 68030 information, so that any
  307.     subsequent program can use the standard methods to identify if the
  308.     system is a 68030 system.
  309.     
  310. */
  311.  
  312. #define PROGRAM_VERSION    "V1.4"
  313.  
  314. #include <exec/types.h>
  315. #include <exec/execbase.h>
  316. #include <exec/nodes.h>
  317. #include <exec/interrupts.h>
  318. #include <functions.h>
  319. #include <stdio.h>
  320.  
  321. /* ====================================================================== */
  322.  
  323. /* Define all bit components used for manipulation of the Cache Control
  324.    Register. */
  325.  
  326. #define CACR_INST    (1L<<0)
  327. #define CACR_DATA    (1L<<8)
  328.  
  329. #define CACR_WALLOC    5
  330. #define CACR_BURST    4
  331. #define CACR_CLEAR    3
  332. #define CACR_ENTRY    2
  333. #define CACR_FREEZE    1
  334. #define CACR_ENABLE    0
  335.  
  336. /* ====================================================================== */
  337.  
  338. /* Define important bits used in various MMU registers. */
  339.  
  340. /* Here are the CRP definitions.  The CRP register is 64 bits long, but
  341.    only the first 32 bits are control bits, the next 32 bits provide the
  342.    base address of the table. */
  343.  
  344. #define    CRP_UPPER    (1L<<31)        /* Upper/lower limit mode */
  345. #define CRP_LIMIT(x)    ((ULONG)((x)&0x7fff)<<16)/* Upper/lower limit value */
  346. #define CRP_SG        (1L<<9)            /* Indicates shared space */
  347. #define CRP_DT_INVALID    0x00            /* Invalid root descriptor */
  348. #define    CRP_DT_PAGE    0x01            /* Fixed offset, auto-genned */
  349. #define CRP_DT_V4BYTE    0x02            /* Short root descriptor */
  350. #define    CRP_DT_V8BYTE    0x03            /* Long root descriptor */
  351.  
  352. /* Here are the TC definitions.  The TC register is 32 bits long. */
  353.  
  354. #define    TC_ENB        (1L<<31)        /* Enable the MMU */
  355. #define    TC_SRE        (1L<<25)        /* For separate Supervisor */
  356. #define    TC_FCL        (1L<<24)        /* Use function codes? */
  357. #define    TC_PS(x)    ((ULONG)((x)&0x0f)<<20)    /* Page size */
  358. #define TC_IS(x)    ((ULONG)((x)&0x0f)<<16)    /* Logical shift */
  359. #define    TC_TIA(x)    ((ULONG)((x)&0x0f)<<12)    /* Table indices */
  360. #define    TC_TIB(x)    ((ULONG)((x)&0x0f)<<8)
  361. #define TC_TIC(x)    ((ULONG)((x)&0x0f)<<4)
  362. #define    TC_TID(x)    ((ULONG)((x)&0x0f)<<0)
  363.  
  364. /* Here are the page descriptor definitions, for short desctriptors only,
  365.    since that's all I'm using at this point. */
  366.    
  367. #define    PD_ADDR(x)    ((ULONG)(x)&~0x0f)    /* Translated Address */
  368. #define    PD_WP        (1L<<2)            /* Write protect it! */
  369. #define PD_DT_INVALID    0x00            /* Invalid root descriptor */
  370. #define    PD_DT_PAGE    0x01            /* Fixed offset, auto-genned */
  371. #define PD_DT_V4BYTE    0x02            /* Short root descriptor */
  372. #define    PD_DT_V8BYTE    0x03            /* Long root descriptor */
  373.  
  374. /* ====================================================================== */
  375.  
  376. /* Some external declarations. */
  377.  
  378. void SetCACR(), GetCRP(), SetCRP(), SetTC();
  379. ULONG GetCACR(), GetTC(), GetCPUType(), GetMMUType(), GetFPUType();
  380.  
  381. /* Checking logic */
  382.  
  383. #define    CK68000    0
  384. #define CK68010    1
  385. #define CK68020    2
  386. #define CK68030    3
  387. #define CK68851    4
  388. #define CK68881    5
  389. #define CK68882    6
  390. #define CKFPU    7
  391. #define CKMMU    8
  392. #define CHECKS    9
  393.  
  394. #define    WARNING    5
  395.  
  396. struct checker { char *item; BOOL tag; };
  397.  
  398. struct checker checks[CHECKS] = {
  399.    { "68000", FALSE },
  400.    { "68010", FALSE },
  401.    { "68020", FALSE },
  402.    { "68030", FALSE },
  403.    { "68851", FALSE },
  404.    { "68881", FALSE },
  405.    { "68882", FALSE },
  406.    { "FPU",   FALSE },
  407.    { "MMU",   FALSE }
  408. };
  409.  
  410. USHORT code = 0L;    /* Program return code */
  411.  
  412. /* ====================================================================== */
  413.  
  414. /* This replaces the Lattice "stricmp()" function, plus it's a better form
  415.    for my needs here. */
  416.    
  417. static BOOL striequ(s1,s2)
  418. char *s1,*s2;
  419. {
  420.    BOOL aok;
  421.    
  422.    while (*s1 && *s2 && (aok = (*s1++ & 0xdf) == (*s2++ & 0xdf)));
  423.    return (BOOL) (!*s1 && aok);
  424. }
  425.  
  426. /* This routine prints FPU codes and sets things accordingly. */
  427.  
  428. static void PrintFPU(fpu)
  429. ULONG fpu;
  430. {
  431.    if (fpu == 68881L) {
  432.       printf("68881 ");
  433.       if (checks[CK68881].tag) code = 0;
  434.    } else if (fpu == 68882L) {
  435.       printf("68882 ");
  436.       if (checks[CK68882].tag) code = 0;
  437.    }
  438.    if (fpu && checks[CKFPU].tag) code = 0;
  439. }
  440.  
  441. /* ====================================================================== */
  442.  
  443. /* Here's the MMU support stuff. */
  444.  
  445. #define ROUND        0x00001000L
  446. #define ROMBASE        0x00FC0000L
  447. #define ROMSIZE        0x00040000L
  448. #define TABSIZE        (128L * sizeof(ULONG))
  449.  
  450. /* Page tables and other MMU stuff must be on a page sized boundary, and
  451.    that boundary must be a power of two.  This routine allocates such an
  452.    aligned block of memory. */
  453.  
  454. static void *AllocAligned(size,bound)
  455. ULONG size;
  456. ULONG bound;
  457. {
  458.    void *mem, *aligned;
  459.    
  460.    if (!(mem = AllocMem(size+bound,0L))) return NULL;   
  461.    Forbid();
  462.    aligned = (void *)(((ULONG)mem + bound - 1) & ~(bound - 1));
  463.    FreeMem(mem,size+bound);
  464.    mem = AllocAbs(size,aligned);
  465.    Permit();
  466.    return mem;
  467. }
  468.  
  469. /* This routine creates the Fast ROM.  If the memory can't be allocated,
  470.    it returns FALSE, otherwise, TRUE.  The "wrapbits" argument probably
  471.    won't work for every case.  There's some magic here which I seem to
  472.    have working, but don't understand completely.  Basically, the TC
  473.    register must be correct, or you'll get a configuration exception,
  474.    otherwise know as GURU #38.  The big constraint is that sum of the
  475.    TIx fields from A to the first zero field, plus PS and IS, must be
  476.    equal to 32. */
  477.  
  478. static BOOL CreateFastROM(wrapbits)
  479. short wrapbits;
  480. {
  481.    ULONG i, myCRP[2], myTC, *ROM32 = NULL, *MMUTable = NULL;
  482.  
  483.   /* First off, get the memory for the 32 bit ROM and the MMU table. */
  484.  
  485.    ROM32 = AllocAligned(ROMSIZE,ROUND);
  486.    MMUTable = AllocAligned(TABSIZE,ROUND);
  487.    if (!ROM32 || !MMUTable) {
  488.       if (MMUTable) FreeMem(MMUTable,TABSIZE);
  489.       if (ROM32)    FreeMem(ROM32,ROMSIZE);
  490.       return FALSE;
  491.    }
  492.  
  493.   /* Here I set up the ROM, as quickly as possible! */
  494.  
  495.    CopyMemQuick(ROMBASE,ROM32,ROMSIZE);
  496.  
  497.   /* Now I initialize the MMU table.  This translation is really very
  498.      basic.  I set up one table level and use direct page translation
  499.      on a grain of 128K per entry.  Everything's directly mapped except
  500.      for the last two entries, which is for the $FC0000-$FFFFFF area.
  501.      This I translate to my fastram ROM, and write protect it too. */
  502.  
  503.    for (i = 0; i < 126; i++) MMUTable[i] = PD_ADDR(i<<17)|PD_DT_PAGE;
  504.    MMUTable[126] = PD_ADDR(ROM32)|PD_WP|PD_DT_PAGE;
  505.    MMUTable[127] = PD_ADDR(((ULONG)ROM32)+0x20000L)|PD_WP|PD_DT_PAGE;
  506.  
  507.   /* Now I have to set up the MMU.  The CPU Root Pointer tells the MMU about 
  508.      the table I've set up, and the Translation Control register will turn 
  509.      the thing on.  Note that the first half of the CRP is control data, the
  510.      second the address of my table. */
  511.  
  512.    myCRP[0] = CRP_LIMIT(0x007f)|CRP_SG|CRP_DT_V4BYTE;
  513.    myCRP[1] = (ULONG)MMUTable;
  514.    SetCRP(myCRP);
  515.  
  516.    myTC = TC_ENB|TC_PS(0x0c)|TC_IS(wrapbits)|
  517.           TC_TIA(0x0f-wrapbits)|TC_TIB(0x05)|TC_TIC(0)|TC_TID(0);
  518.    SetTC(myTC);
  519.    return TRUE;
  520. }
  521.  
  522. /* This routine remover the Fast ROM, and re-claims the memory previously
  523.    allocated.  We've already checked to make sure that the MMU was 
  524.    switched on. */
  525.  
  526. static void DeleteFastROM() {
  527.    ULONG myCRP[2], *ROM32 = NULL, *MMUTable = NULL;
  528.  
  529.   /* First off, turn of the MMU.  This lets us muck with the table and
  530.      reclaim memory without any trouble. */
  531.  
  532.    SetTC(0L);
  533.  
  534.   /* Now get the root pointer, which will tell where the memory has been
  535.      allocated. */
  536.  
  537.    GetCRP(myCRP);
  538.    MMUTable = (ULONG *)myCRP[1];
  539.    ROM32 = (ULONG *)PD_ADDR(MMUTable[126]);
  540.  
  541.   /* Now I just free up the memory, and I'm done! */
  542.   
  543.    FreeMem(MMUTable,TABSIZE);
  544.    FreeMem(ROM32,ROMSIZE);
  545. }
  546.  
  547. /* ====================================================================== */
  548.  
  549. /* Codes for the FASTROM action. */
  550.  
  551. #define    FR_NO_ACTION    0
  552. #define    FR_CREATE    1
  553. #define    FR_DELETE    2
  554.  
  555. /* This be the main program. */
  556.  
  557. int main(argc,argv)
  558. int argc;
  559. char *argv[];
  560. {
  561.    BOOL worked, dommutest = TRUE, fastrom = FR_NO_ACTION;
  562.    ULONG cacr,op,mode,test,cpu,fpu,mmu = 0;
  563.    USHORT i,j;
  564.    short wrapbits = 8;
  565.  
  566.    /* If they're just asking for help */
  567.  
  568.    if (argc >= 2 && argv[1][0] == '?') {
  569.       printf("\2337mSetCPU %s by Dave Haynie\2330m\n",PROGRAM_VERSION);
  570.       printf("Usage: SetCPU [INST|DATA] [[NO]CACHE|[NO]BURST]\n");
  571.       printf("              [[NO]FASTROM [TRAP]] [NOMMUTEST]\n");
  572.       printf("              [CHECK 680x0|68851|6888x|MMU|FPU]\n");
  573.       exit(0);
  574.    }
  575.  
  576.   /* Now we parse the command line.  The default cache operation acts on 
  577.      both data and instruction caches.  The way all the cache control
  578.      functions are defined, they're just NOPs on machines without the
  579.      appropriate caches. */
  580.    
  581.    mode = CACR_INST | CACR_DATA;
  582.    cacr = GetCACR();
  583.  
  584.    if (argc > 1) {
  585.       for (i = 1; i < argc; ++i) {
  586.          if (code == WARNING) for (j = 0; j < CHECKS; ++j)
  587.             if (striequ(checks[j].item,argv[i])) {
  588.                checks[j].tag = TRUE;
  589.                break;
  590.             }
  591.          if (striequ(argv[i],"CHECK"))        code = WARNING;
  592.          else if (striequ(argv[i],"FASTROM"))    fastrom = FR_CREATE;
  593.          else if (striequ(argv[i],"NOFASTROM"))    fastrom = FR_DELETE;
  594.          else if (striequ(argv[i],"TRAP"))    wrapbits = 0;
  595.          else if (striequ(argv[i],"NOMMUTEST"))    dommutest = FALSE;
  596.          else if (striequ(argv[i],"DATA"))    mode = CACR_DATA;
  597.          else if (striequ(argv[i],"INST"))    mode = CACR_INST;
  598.          else if (striequ(argv[i],"CACHE"))    cacr |=   mode << CACR_ENABLE;
  599.          else if (striequ(argv[i],"NOCACHE"))    cacr &= ~(mode << CACR_ENABLE);
  600.          else if (striequ(argv[i],"BURST"))    cacr |=   mode << CACR_BURST;
  601.          else if (striequ(argv[i],"NOBURST"))    cacr &= ~(mode << CACR_BURST);
  602.       }
  603.  
  604.      /* We ALWAYs want to be in Word Allocate mode, AmigaOS won't run 
  605.         otherwise. */
  606.  
  607.       SetCACR(cacr | CACR_DATA << CACR_WALLOC);
  608.    }
  609.  
  610.   /* Let's find out what we have, and perform the ROM translation, if it's
  611.      requested and hasn't been done already. */
  612.  
  613.    cpu = GetCPUType();
  614.    fpu = GetFPUType();
  615.    if (dommutest && (mmu = GetMMUType())) {
  616.       if (!(GetTC() & TC_ENB)) {
  617.          if (fastrom == FR_CREATE && !CreateFastROM(wrapbits)) {
  618.             printf("Error: Can't get memory for FASTROM translation\n");
  619.             exit(10);
  620.          }
  621.       } else if (fastrom == FR_DELETE)
  622.          DeleteFastROM();
  623.    }
  624.  
  625.    printf("SYSTEM: ");
  626.  
  627.    /* If they're not on a 68020/68030, we can't set anything.  For 
  628.       compatibility across systems, I don't consider a cache setting 
  629.       request an error, just ignore it. */
  630.  
  631.    if (cpu <= 68010L) {
  632.       if (cpu == 68010L) {
  633.          printf("68010 ");
  634.          if (checks[CK68010].tag) code = 0;
  635.       } else {
  636.          printf("68000 ");
  637.          if (checks[CK68000].tag) code = 0;
  638.       }
  639.       PrintFPU(fpu);
  640.       printf("\n");
  641.       exit(code);
  642.    }
  643.  
  644.    /* Now we're on a 32 bit system.  But EXEC doesn't know which.  If you
  645.       run SetCPU on a 68030 system once, the '030 flag's set, otherwise, 
  646.       we'll test for it. */
  647.  
  648.    if (cpu == 68030L) {
  649.       printf("68030 ");
  650.       if (checks[CK68030].tag) code = 0;
  651.    } else {
  652.       printf("68020 ");
  653.       if (checks[CK68020].tag) code = 0;
  654.    }
  655.  
  656.    PrintFPU(fpu);
  657.  
  658.    if (mmu == 68851L) {
  659.       printf("68851 ");
  660.       if (checks[CK68851].tag) code = 0;
  661.    }
  662.    if (mmu && checks[CKMMU].tag) code = 0;
  663.    if (mmu && (GetTC() & TC_ENB)) printf("FASTROM ");
  664.  
  665.    /* We always print the results, even if nothing has changed. */
  666.    
  667.    cacr = GetCACR();
  668.    printf("(INST: ");
  669.    if (!(cacr & (CACR_INST << CACR_ENABLE))) printf("NO");
  670.    printf("CACHE");
  671.  
  672.    if (cpu == 68030L) {
  673.       printf(" ");
  674.       if (!(cacr & (CACR_INST << CACR_BURST))) printf("NO");
  675.       printf("BURST) (DATA: ");
  676.       if (!(cacr & (CACR_DATA << CACR_ENABLE))) 
  677.          printf("NOCACHE ");
  678.       else
  679.          printf("CACHE ");
  680.  
  681.       if (!(cacr & (CACR_DATA << CACR_BURST))) printf("NO");
  682.       printf("BURST");
  683.    }
  684.    printf(")\n");
  685.  
  686.    /* For safety's sake, or personal paranoia, or whatever, I dump the
  687.       data cache before I go away. */
  688.  
  689.    if (cpu = 68030L) SetCACR(cacr|(CACR_DATA << CACR_CLEAR));
  690.    exit(code);
  691. }
  692.  
  693. SHAR_EOF
  694. cat << \SHAR_EOF > 030Stuff.a
  695. ;======================================================================
  696. ;
  697. ;    SetCPU V1.4
  698. ;    by Dave Haynie (released to the public domain)
  699. ;
  700. ;    68030 Assembly Function Module
  701. ;
  702. ;    This module contains functions that access functions in the 68020,
  703. ;    68030, and 68851 chips, and ID all of these, plus the 68881/68882
  704. ;    FPU chips.
  705. ;
  706. ;======================================================================
  707.  
  708. ;======================================================================
  709. ;
  710. ;    Macros & constants used herein...
  711. ;
  712. ;======================================================================
  713.  
  714. CALLSYS macro   *
  715.     jsr     LVO\1(A6)
  716.     endm
  717.  
  718. CIB_ENABLE    EQU    0
  719. CIB_FREEZE    EQU    1
  720. CIB_ENTRY    EQU    2
  721. CIB_CLEAR    EQU    3
  722. CIB_BURST    EQU    4
  723.  
  724. CDB_ENABLE    EQU    8
  725. CDB_FREEZE    EQU    9
  726. CDB_ENTRY    EQU    10
  727. CDB_CLEAR    EQU    11
  728. CDB_BURST    EQU    12
  729. CDB_WALLOC    EQU    13
  730.  
  731. AFB_68030    EQU    2
  732.  
  733. ATNFLGS        EQU    $129
  734.  
  735. LVOSupervisor    EQU    -30
  736. LVOFindTask    EQU    -294
  737. LVOAllocTrap    EQU    -342
  738. LVOFreeTrap    EQU    -348
  739.  
  740. ;======================================================================
  741. ;
  742. ;    Need just a little more stuff
  743. ;
  744. ;======================================================================
  745.  
  746.     NOLIST
  747.     include "exec/execbase.i"
  748.     include "exec/tasks.i"
  749.     LIST
  750.  
  751.     machine mc68020
  752.         mc68881
  753.     cseg
  754.  
  755. ;**********************************************************************
  756. ;
  757. ;    This section contains functions that identify and operate on CPU 
  758. ;    things.
  759. ;
  760. ;**********************************************************************
  761.  
  762.     public    _GetCPUType    ; ID the CPU
  763.     public    _GetCACR    ; Get 020/030 CACR register
  764.     public    _SetCACR    ; Set 020/030 CACR register
  765.  
  766. ;======================================================================
  767. ;
  768. ;    This function returns the type of the CPU in the system as a
  769. ;    longword: 68000, 68010, 68020, or 68030.  The testing must be done
  770. ;    in reverse order, in that any higher CPU also has the bits set for
  771. ;    a lower CPU.  Also, since 1.3 doesn't recognize the 68030, if I
  772. ;    find the 68020 bit set, I always check for the presence of a 
  773. ;    68030.
  774. ;
  775. ;    This routine should be the first test routine called under 1.2
  776. ;    and 1.3.
  777. ;
  778. ;    ULONG GetCPUType();
  779. ;
  780. ;======================================================================
  781.  
  782. _GetCPUType:
  783.     movem.l    a4/a5,-(sp)        ; Save this register
  784.     move.l    4,a6            ; Get ExecBase
  785.     btst.b    #AFB_68030,ATNFLGS(a6)    ; Does the OS think an '030 is here?
  786.     beq    0$
  787.     move.l    #68030,d0        ; Sure does...
  788.     movem.l    (sp)+,a4/a5
  789.     rts
  790. 0$
  791.     btst.b    #AFB_68020,ATNFLGS(a6)    ; Maybe a 68020
  792.     bne    2$
  793.     btst.b    #AFB_68010,ATNFLGS(a6)    ; Maybe a 68010?
  794.     bne    1$
  795.     move.l    #68000,d0        ; Just a measley '000
  796.     movem.l    (sp)+,a4/a5
  797.     rts
  798. 1$
  799.     move.l    #68010,d0        ; Yup, we're an '010
  800.     movem.l    (sp)+,a4/a5
  801.     rts
  802. 2$
  803.     move.l    #68020,d0        ; Assume we're an '020
  804.     lea    3$,a5            ; Get the start of the supervisor code
  805.     CALLSYS    Supervisor
  806.     movem.l    (sp)+,a4/a5
  807.     rts
  808. 3$
  809.     movec    cacr,d1            ; Get the cache register
  810.     move.l    d1,a4            ; Save it for a minute
  811.     bset.l    #CIB_BURST,d1        ; Set the inst burst bit
  812.     bclr.l    #CIB_ENABLE,d1        ; Clear the inst cache bit
  813.     movec    d1,cacr            ; Try to set the CACR
  814.     movec    cacr,d1
  815.     btst.l    #CIB_BURST,d1        ; Do we have a set burst bit?
  816.     beq    4$
  817.     move.l    #68030,d0        ; It's a 68030
  818.     bset.b    #AFB_68030,ATNFLGS(a6)
  819. 4$
  820.     move.l    a4,d1            ; Restore the original CACR
  821.     movec    d1,cacr
  822.     rte
  823.  
  824. ;======================================================================
  825. ;
  826. ;    This function returns the 68020/68030 CACR register.  It assumes
  827. ;    a 68020 or 68030 based system.
  828. ;
  829. ;    ULONG GetCACR()
  830. ;
  831. ;======================================================================
  832.  
  833. _GetCACR:
  834.     move.l    4,a6            ; Get ExecBase
  835.     btst.b    #AFB_68020,ATNFLGS(a6)    ; Does the OS think an '020 is here?
  836.     bne    1$
  837.     moveq.l    #0,d0            ; No CACR here, pal
  838.     rts
  839. 1$
  840.     move.l    a5,-(sp)        ; Save this register
  841.     lea    2$,a5            ; Get the start of the supervisor code
  842.     CALLSYS    Supervisor
  843.     move.l    (sp)+,a5        ; Give back registers
  844.     rts
  845. 2$
  846.     movec    cacr,d0            ; Make CACR the return value
  847.     rte
  848.  
  849. ;======================================================================
  850. ;
  851. ;    This function sets the value of the 68020/68030 CACR register.  
  852. ;    It assumes a 68020 or 68030 based system.
  853. ;
  854. ;    void SetCACR(cacr)
  855. ;    ULONG cacr;
  856. ;
  857. ;======================================================================
  858.  
  859. _SetCACR:
  860.     move.l    4(sp),d0        ; New CACR is on stack
  861.     move.l    4,a6            ; Get ExecBase
  862.     btst.b    #AFB_68020,ATNFLGS(a6)    ; Does the OS think an '020 is here?
  863.     bne    1$
  864.     rts                ; No CACR here, pal
  865. 1$
  866.     move.l    a5,-(sp)        ; Save this register
  867.     lea    2$,a5            ; Get the start of the supervisor code
  868.     CALLSYS    Supervisor
  869.     move.l    (sp)+,a5        ; Give back register
  870.     rts
  871. 2$
  872.     movec    d0,cacr            ; Set the CACR
  873.     rte
  874.  
  875. ;**********************************************************************
  876. ;
  877. ;    This section contains functions that identify and operate on
  878. ;    MMU things.  Unfortunately, there aren't any MMU op-codes in
  879. ;    the Manx assembler yet, so I have to fudge them here.
  880. ;
  881. ;**********************************************************************
  882.  
  883.     public    _GetMMUType    ; Returns the type of MMU
  884.     public    _GetCRP        ; Gets MMU CRP register
  885.     public    _SetCRP        ; Sets MMU CRP register
  886.     public    _GetTC        ; Gets MMU TC register
  887.     public    _SetTC        ; Gets MMU TC register
  888.  
  889. ;======================================================================
  890. ;
  891. ;    This function returns 0L if the system contains no MMU, 
  892. ;    68851L if the system does contain an 68851, or 68030L if the
  893. ;    system contains a 68030.
  894. ;
  895. ;    This routine seems to lock up on at least some CSA 68020 
  896. ;    boards, though it runs just fine on those from Ronin and 
  897. ;    Commodore, as well as all 68030 boards it's been tested on.
  898. ;
  899. ;    ULONG GetMMUType()
  900. ;
  901. ;======================================================================
  902.  
  903. _GetMMUType:
  904.     move.l    4,a6            ; Get ExecBase
  905.     movem.l    a3/a4/a5,-(sp)        ; Save this stuff
  906.     move.l    #0,a1    
  907.     CALLSYS    FindTask        ; Call FindTask(0L)
  908.     move.l    d0,a3
  909.  
  910.     move.l    TC_TRAPCODE(a3),a4    ; Change the exception vector
  911.     move.l    #2$,TC_TRAPCODE(a3)
  912.     
  913.     subq.l    #4,sp            ; Let's try an MMU instruction
  914.     dc.w    $f017            ; Slimey PMOVE tc,(sp)
  915.     dc.w    $4200
  916.     cmpi    #0,d0            ; Any MMU here?
  917.     beq    1$
  918.     btst.b    #AFB_68030,ATNFLGS(a6)    ; Does the OS think an '030 is here?
  919.     beq    1$
  920.     move.l    #68030,d0
  921.  
  922. 1$
  923.     addq.l    #4,sp            ; Return that local
  924.     move.l    a4,TC_TRAPCODE(a3)    ; Reset exception stuff
  925.     movem.l    (sp)+,a3/a4/a5        ; and return the registers
  926.     rts
  927.  
  928.     ; This is the exception code.  No matter what machine we're on,
  929.     ; we get an exception.  If the MMU's in place, we should get a
  930.     ; privilige violation; if not, an F-Line emulation exception.
  931. 2$
  932.     move.l    (sp)+,d0        ; Get Amiga supplied exception #
  933.     cmpi    #11,d0            ; Is it an F-Line?
  934.     beq    3$            ; If so, go to the fail routine
  935.     move.l    #68851,d0        ; We have MMU
  936.     addq.l    #4,2(sp)        ; Skip the MMU instruction
  937.     rte
  938. 3$
  939.     moveq.l    #0,d0            ; It dinna woik,
  940.     addq.l    #4,2(sp)        ; Skip the MMU instruction
  941.     rte
  942.  
  943. ;======================================================================
  944. ;
  945. ;    This function returns the MMU CRP register.  It assumes a 68020 
  946. ;    system with MMU, or a 68030 based system (eg, test for MMU before
  947. ;    you call this, or you wind up in The Guru Zone).  Note that the
  948. ;    CRP register is two longwords long.
  949. ;
  950. ;    void GetCRP(ULONG *)
  951. ;
  952. ;======================================================================
  953.  
  954. _GetCRP:
  955.     move.l    4(sp),a0        ; Pointer to the CRP storage area
  956.     move.l    4,a6            ; Get ExecBase
  957.     move.l    a5,-(sp)
  958.     lea    2$,a5            ; Get the start of the supervisor code
  959.     CALLSYS    Supervisor
  960.     move.l    (sp)+,a5
  961.     rts
  962. 2$
  963.     dc.w    $f010            ; PMOVE CRP,(a0)
  964.     dc.w    $4e00
  965.     rte
  966.  
  967. ;======================================================================
  968. ;
  969. ;    This function sets the MMU CRP register.  It assumes a 68020 
  970. ;    system with MMU, or a 68030 based system (eg, test for MMU before
  971. ;    you call this, or you wind up in The Guru Zone).  Note that the
  972. ;    CRP register is two longwords long.
  973. ;
  974. ;    void SetCRP(ULONG *)
  975. ;
  976. ;======================================================================
  977.  
  978. _SetCRP:
  979.     move.l    4(sp),a0        ; Pointer to the CRP storage area
  980.     move.l    4,a6            ; Get ExecBase
  981.     move.l    a5,-(sp)
  982.     lea    2$,a5            ; Get the start of the supervisor code
  983.     CALLSYS    Supervisor
  984.     move.l    (sp)+,a5        ; Give back registers
  985.     rts
  986. 2$
  987.     dc.w    $f010            ; PMOVE (a0),CRP
  988.     dc.w    $4c00
  989.     rte
  990.  
  991. ;======================================================================
  992. ;
  993. ;    This function returns the MMU TC register.  It assumes a 68020 
  994. ;    system with MMU, or a 68030 based system (eg, test for MMU before
  995. ;    you call this, or you wind up in The Guru Zone).  
  996. ;
  997. ;    ULONG GetTC()
  998. ;
  999. ;======================================================================
  1000.  
  1001. _GetTC:
  1002.     move.l    4,a6            ; Get ExecBase
  1003.     move.l    a5,-(sp)
  1004.     subq.l    #4,sp            ; Make a place to dump TC
  1005.     move.l    sp,a0
  1006.     lea    2$,a5            ; Get the start of the supervisor code
  1007.     CALLSYS    Supervisor
  1008.     move.l    (sp),d0            ; Here's the result
  1009.     addq.l    #4,sp
  1010.     move.l    (sp)+,a5
  1011.     rts
  1012. 2$
  1013.     dc.w    $f010            ; PMOVE TC,(a0)
  1014.     dc.w    $4200
  1015.     rte
  1016.  
  1017. ;======================================================================
  1018. ;
  1019. ;    This function sets the MMU TC register.  It assumes a 68020 
  1020. ;    system with MMU, or a 68030 based system (eg, test for MMU before
  1021. ;    you call this, or you wind up in The Guru Zone).  
  1022. ;
  1023. ;    void SetTC(ULONG)
  1024. ;
  1025. ;======================================================================
  1026.  
  1027. _SetTC:
  1028.     lea    4(sp),a0        ; Get address of our new TC value
  1029.     move.l    4,a6            ; Get ExecBase
  1030.     move.l    a5,-(sp)
  1031.     lea    2$,a5            ; Get the start of the supervisor code
  1032.      CALLSYS    Supervisor
  1033.     move.l    (sp)+,a5
  1034.     rts
  1035. 2$
  1036.     dc.w    $f010            ; PMOVE (a0),TC
  1037.     dc.w    $4000
  1038.     rte
  1039.  
  1040.  
  1041. ;**********************************************************************
  1042. ;
  1043. ;    This section contains functions that identify and operate on
  1044. ;    FPU things.  
  1045. ;
  1046. ;**********************************************************************
  1047.  
  1048.     public    _GetFPUType    ; Gets the FPU type
  1049.  
  1050. ;======================================================================
  1051. ;
  1052. ;    This function returns the type of the FPU in the system as a
  1053. ;    longword: 0 (no FPU), 68881, or 68882.
  1054. ;
  1055. ;    ULONG GetFPUType();
  1056. ;
  1057. ;======================================================================
  1058.  
  1059. _GetFPUType:
  1060.     move.l    a5,-(sp)        ; Save this register
  1061.     move.l    4,a6            ; Get ExecBase
  1062.     btst.b    #AFB_68881,ATNFLGS(a6)    ; Does the OS think an FPU is here?
  1063.     bne    1$    
  1064.     moveq.l    #0,d0            ; No FPU here, dude
  1065.     move.l    (sp)+,a5        ; Give back the register
  1066.     rts
  1067. 1$
  1068.     lea    2$,a5            ; Get the start of the supervisor code
  1069.     CALLSYS    Supervisor
  1070.     move.l    (sp)+,a5        ; Give back registers
  1071.     rts
  1072. 2$
  1073.     move.l    #68881,d0        ; Assume we're a 68881
  1074.     fsave    -(sp)            ; Test and check
  1075.     moveq.l    #0,d1
  1076.     move.b    1(sp),d1        ; Size of this frame
  1077.     cmpi    #$18,d1
  1078.     beq 3$
  1079.     move.l    #68882,d0        ; It's a 68882
  1080. 3$
  1081.     frestore (sp)+            ; Restore the stack
  1082.     rte
  1083.  
  1084.     end
  1085. SHAR_EOF
  1086. cat << \SHAR_EOF > makefile
  1087. ######################################################################
  1088. #
  1089. # Makefile for SetCPU V1.3
  1090. #
  1091. ######################################################################
  1092.  
  1093. .a.o:
  1094.     as -o $@ $*.a
  1095.  
  1096. CFLAGS    = +x5
  1097. LFLAGS    = -lc
  1098.  
  1099. OBJS    = 030stuff.o setcpu.o
  1100.  
  1101. SetCPU:        $(OBJS)
  1102.         ln $(OBJS) -o SetCPU $(LFLAGS)
  1103.  
  1104. ROMBash:    ROMBash.o
  1105.         ln $*.o -o ROMBash $(LFLAGS)
  1106. SHAR_EOF
  1107. cat << \SHAR_EOF > RomBash.uu
  1108.  
  1109. begin 644 ROMBash
  1110. M```#\P`````````#``````````(```2O````JP````$```/I```$KT[Z`:1.T
  1111. M5?_Z0J=(>0`#``!.NA&R4$\K0/_Z0FW__DAY``,``"\M__I(>0#\``!.NA%J.
  1112. M3^\`#%)M__X,;0!D__YMW$AY``,``"\M__I.NA&V4$].74YU3E7_HD'Z`.HKR
  1113. M2/_H0BW_[$*G3KH1@EA/*T#_[DAX__].NA%`6$\;0/_M2&W_WDZZ$2983T'MW
  1114. M_]XK2/_$0J=(;?^V0J=(>@"R3KH1D$_O`!!*0&<82'H`QDAZ`*M.N@5L4$\_/
  1115. M/``43KH.KE1/*6W_RH)>.WP`"O_22&W_MDZZ$0)83T'M_ZI#[?_6(-D@V4ZZ*
  1116. M_QY(;?^V3KH0Z%A/0>W_HD/M_]8@V2#92&W_JDAM_Z).NA&F4$\O+?^F+RW_B
  1117. MHDAZ`&E.N@4&3^\`#$AM_[9.NA!86$](;?_>3KH1)EA/<``0+?_M+P!.NA#:=
  1118. M6$].74YU4D]-0F%S:`!T:6UE<BYD979I8V4`17)R;W(Z($-A;B=T(&=E="`BS
  1119. M)7,B"@!T:6UE<BYD979I8V4`1$].13H@16QA<'-E9"!T:6UE(#T@)6QD+B4V+
  1120. M;&0@<V5C;VYD<PH`87!#[():1>R"6K7)9@XR/``4:PAT`"+"4<G__"E/@F(LN
  1121. M>``$*4Z"9DCG@(`(+@`$`2EG$$OZ``A.KO_B8`9"I_-?3G-#^@`@3J[^:"E`9
  1122. M@FIF#"X\``.`!TZN_Y1@!$ZZ`!I03TYU9&]S+FQI8G)A<GD`2?D``'_^3G5."
  1123. M50``+PI(>0`!```P+().P?P`!B\`3KH/D"E`@FY03V840J=(>0`!``!.N@\:C
  1124. M4$\N;()B3G4@;()N0F@`!"!L@FXQ?``!`!`@;()N,7P``0`*(&R"8B`L@F*0H
  1125. MJ``$4(`I0()R(&R"<B"\34%.6$*G3KH/7B1`2JH`K%A/9RXO+0`,+RT`""\*,
  1126. M3KH`KCE\``&"=B!L@FX`:(````0@;()N`&B````*3^\`#&!"2&H`7$ZZ#ZI(]
  1127. M:@!<3KH/2BE`@G@@;()X2J@`)%!/9Q`@;()X(F@`)"\13KH.!EA/+RR">"\*!
  1128. M3KH":"EL@GB"?%!/3KH.!B!L@FX@@$ZZ#B8@;()N(4``!F<62'@#[4AZ`"I.<
  1129. MN@X"(&R";B%```Q03R\L@GP_+(*`3KK]$$)G3KH,(%!/)%].74YU*@!.50``G
  1130. M2.<,,"1M`!`@;0`(2J@`K&<8(&T`""`H`*SE@"@`($0@*``0Y8`F0&`$)FR"3
  1131. M4!`32(!(P-"M``Q4@#E`@H)"IS`L@H)(P"\`3KH.(BE`@H103V8(3-\,,$Y=C
  1132. M3G40$TB`.@`_!2!+4H@O""\L@H1.N@%^,`5(P"!`T>R"A$/Z`400V6;\/RT`I
  1133. M#B\*+RR"A$ZZ`3H@;(*$0C!0`#E\``&"@#`%2,#0K(*$)D!2BR1+3^\`%!`3=
  1134. M2(`Z`+!\`"!G&+I\``EG$KI\``QG#+I\``UG!KI\``IF!%*+8-@,$P`@;7H,;
  1135. M$P`B9BY2BR!+4HL0$$B`.@!G'B!*4HH0A;I\`")F$`P3`")F!%*+8`9"*O__6
  1136. M8`)@UF`X($M2BQ`02(`Z`&<FNGP`(&<@NGP`"6<:NGP`#&<4NGP`#6<.NGP`O
  1137. M"F<(($I2BA"%8,X@2E**0A!*168"4XM2;(*`8`#_6D(20J<P+(*`4D!(P.6`"
  1138. M+P!.N@T`*4""?%!/9@A";(*`8`#^V'H`)FR"A&`D,`5(P.6`(&R"?"&+"``@T
  1139. M2R`(2AAF_)'`4X@P"%)`2,#7P%)%NFR"@&W6,`5(P.6`(&R"?$*P"`!@`/Z4F
  1140. M(``P/'__8`0P+P`,(&\`!$H89OQ32")O``A30!#95\C__&<"0A`@+P`$3G5,7
  1141. M[P,```0@"#(O``Q@`A#95\G__&<&4D%@`D(84<G__$YU3E4``$CG#C`D;0`(N
  1142. M0J=(>@".3KH,QBE`@HA03V8(3-\,<$Y=3G4@;0`,(F@`)"\I``1.N@T"*`!8B
  1143. M3V=22'H`;2!$+R@`-DZZ#-0F0$J`4$]G-$AX`^TO"TZZ"VPL`%!/9R0@!N6`$
  1144. M*@`@125H``@`I"5&`)Q(>`/M2'H`.$ZZ"T@E0`"@4$\O!$ZZ#*!83R\L@HA.Y
  1145. MN@N*0JR"B%A/8(!I8V]N+FQI8G)A<GD`5TE.1$]7`"H`3E4``$AM``PO+0`(D
  1146. M2'H$8$ZZ`)A/[P`,3EU.=4Y5``!(YP@@)&T`#@QM``0`$F8((&T`""@08!Q*G
  1147. M;0`,;PP@;0`(<``P$"@`8`H@;0`(,!!(P"@`0FT`$DIM``QL$$1M``Q*A&P(/
  1148. M1(0[?``!`!(R+0`,2,$@!$ZZ`Y!![(`"4XH4L```,BT`#$C!(`1.N@.&*`!F,
  1149. MVDIM`!)G!E.*%+P`+2`*3-\$$$Y=3G5.5?\B2.<(,"1M``@F;0`,0FW_^BMMD
  1150. M`!#__"!+4HL0$$B`.`!G``+NN'P`)68``LQ"+?\P.WP``?_X.WP`(/_V.WPG.
  1151. M$/_T($M2BQ`02(`X`+!\`"UF#D)M__@@2U*+$!!(@#@`N'P`,&80.WP`,/_V\
  1152. M($M2BQ`02(`X`+A\`"IF&"!M__Q4K?_\.U#_\B!+4HL0$$B`.`!@,D)M__)@^
  1153. M'#`M__+!_``*T$20?``P.T#_\B!+4HL0$$B`.``P!%)`0>R`%`@P``(``&;40
  1154. MN'P`+F9:($M2BQ`02(`X`+!\`"IF&"!M__Q4K?_\.U#_]"!+4HL0$$B`.`!@H
  1155. M,D)M__1@'#`M__3!_``*T$20?``P.T#_]"!+4HL0$$B`.``P!%)`0>R`%`@P,
  1156. M``(``&;4.WP``O_PN'P`;&82($M2BQ`02(`X`#M\``3_\&`0N'P`:&8*($M2'
  1157. MBQ`02(`X`#`$2,!@>CM\``C_[F`6.WP`"O_N8`X[?``0_^Y@!CM\__;_[C\M>
  1158. M__!(;?\P/RW_[B\M__Q.NOWD*T#_ZC`M__!(P-&M__Q/[P`,8%P@;?_\6*W_?
  1159. M_")0*TG_ZB`)2AEF_)/`4XD[2?_P8$H@;?_\5*W__#@00>W_+RM(_^H0A&`HE
  1160. MD+P```!C9^)3@&>2D+P````+9P#_<EF`9[)5@&<`_W!7@&<`_W)@S$'M_S"19
  1161. M[?_J.TC_\#`M__"P;?_T;P8[;?_T__!*;?_X9V@@;?_J#!``+6<*(&W_Z@P0B
  1162. M`"MF+@QM`##_]F8F4VW_\B!M_^I2K?_J$!!(@#\`3I*P?/__5$]F"G#_3-\,B
  1163. M$$Y=3G5@%C\M__9.DK!\__]43V8$</]@Y%)M__HP+?_R4VW_\K!M__!NW$)M;
  1164. M_^Y@("!M_^I2K?_J$!!(@#\`3I*P?/__5$]F!'#_8+!2;?_N(&W_ZDH09PHPE
  1165. M+?_NL&W_]&W.,"W_[M%M__I*;?_X9BA@&#\\`"!.DK!\__]43V8&</]@`/]X4
  1166. M4FW_^C`M__)3;?_RL&W_\&[:8!8_!$Z2L'S__U1/9@9P_V``_U)2;?_Z8`#]2
  1167. M"#`M__I@`/]"2.=(`$*$2H!J!$2`4D1*@6H&1($*1``!83Y*1&<"1(!,WP`2T
  1168. M2H!.=4CG2`!"A$J`:@1$@%)$2H%J`D2!81H@`6#8+P%A$B`!(A]*@$YU+P%A/
  1169. M!B(?2H!.=4CG,`!(04I!9B!(038!-`!"0$A`@,,B`$A`,@*"PS`!0D%(04S?9
  1170. M``Q.=4A!)@$B`$)!2$%(0$)`=`_0@-.!MH%B!)*#4D!1RO_R3-\`#$YU3E4`+
  1171. M`$AL@*P_+0`(3KH`"%Q/3EU.=4Y5```O!#@M``@O+0`*/P1.N@`PN'P`"EQ/*
  1172. M9B0@;0`*$"@`#$B`"```!V<4/SS__R\M``I.N@#T7$\H'TY=3G5@^$Y5```O<
  1173. M"B1M``H@4K'J``1E&#`M``C`?`#_/P`O"DZZ`,A<3R1?3EU.=2!24I(0+0`)3
  1174. M$(!(@,!\`/]@Z$Y5```O"D'L@)8D2"!*U?P````6+PAA$%A/0>R"3K7(9>HDS
  1175. M7TY=3G5.50``2.<(("1M``AX`"`*9@IP_TS?!!!.74YU2BH`#&=0""H``@`,%
  1176. M9PP_//__+PIA4C@`7$\0*@`-2(`_`$ZZ!1R(0`@J``$`#%1/9PHO*@`(3KH"X
  1177. M+EA/""H`!0`,9Q(O*@`23KH"P"\J`!).N@(44$]"DD*J``1"J@`(0BH`##`$2
  1178. M8)!.5?_^2.<(("1M``A!^O]&*4B"C`@J``0`#&<*</],WP003EU.=0@J``(`"
  1179. M#&<P(%*1Z@`(.`@_!"\J``@0*@`-2(`_`$ZZ`H"P1%!/9Q`(Z@`$``Q"DD*J@
  1180. M``1P_V#`#&W__P`,9A`(J@`"``Q"DD*J``1P`&"H2JH`"&8(+PI.N@":6$\,`
  1181. M:@`!`!!F*AMM``W__S\\``%(;?__$"H`#4B`/P!.N@(BL'P``5!/9J`P+0`,"
  1182. M8`#_:B2J``@P*@`02,#0J@`()4``!`CJ``(`#"!24I(0+0`-$(!(@,!\`/]@/
  1183. M`/\^3E4``"\*0>R`EB1(2BH`#&<8U?P````60>R"3K7(90AP`"1?3EU.=6#BX
  1184. M0I)"J@`$0JH`""`*8.I.5?_\+PHD;0`(/SP$`$ZZ`,`K0/_\5$]F\``$`<
  1185. M$"!*T?P````.)4@`""1?3EU.=35\!```$`CJ``$`#"5M__P`"!`J``U(@#\`B
  1186. M3KH`XDI`5$]G!@`J`(``#&#.3E4``$CG`#`D;():8!0F4B`J``10@"\`+PI.6
  1187. MN@2F4$\D2R`*9NA"K():3-\,`$Y=3G5.50``+PI!^O_&*4B"D$*G("T`"%"`&
  1188. M+P!.N@0V)$!*@%!/9@AP`"1?3EU.=22L@EHE;0`(``0I2H):(`I0@&#F3E4`)
  1189. M`'``,"T`""\`8;)83TY=3G5.50``2.<`,)?+)&R"6F`.(&T`"%&(L<IG$B9*\
  1190. M)%(@"F;N</],WPP`3EU.=2`+9P0FDF`$*5*"6B`J``10@"\`+PI.N@/X<`!0:
  1191. M3V#83E4``"\*,"T`",'\``8D0-7L@FY*;0`(;0XP+0`(L&R"3FP$2I)F#CE\@
  1192. M``*"E'#_)%].74YU,"T`",'\``8@;()N+S`(`$ZZ`L9*@%A/9P1P`6`"<`!@2
  1193. MV$Y5```O+0`(3KH"D$J`6$]F#DZZ`IHY0(*4</].74YU<`!@^$Y5``!(YPP@T
  1194. M."T`"$ZZ`'`P!,'\``8D0-7L@FY*1&T*N&R"3FP$2I)F$#E\``*"E'#_3-\$7
  1195. M,$Y=3G4P*@`$P'P``V8*.7P`!8*4</]@Y'``,"T`#B\`+RT`"B\23KH"9BH`Y
  1196. ML+S_____3^\`#&8,3KH"&CE`@I1P_V"X(`5@M$Y5__Q(>!``0J=.N@-0*T#_S
  1197. M_`@```Q03V<22FR"=F8(("W__$Y=3G5.N@`&<`!@]$Y5``!(>``$2'H`'$ZZ9
  1198. M`?`O`$ZZ`@(_/``!3KH`#D_O``Y.74YU7D,*`$Y5``!*K(*,9P8@;(*,3I`_N
  1199. M+0`(3KH`"%1/3EU.=4Y5__PO!#`M``A(P"M`__Q*K()N9RAX`&`*/P1.N@#^:
  1200. M5$]21+AL@DYM\#`L@D[!_``&+P`O+()N3KH"1%!/2JR"D&<&(&R"D$Z02JR")
  1201. M5&<*+RR"5$ZZ`6A83TJL@I9G""!L@I8@K(*:2JR"GF<*+RR"GDZZ`9!83TJL/
  1202. M@J)G"B\L@J).N@&`6$]*K(*F9PHO+(*F3KH!<%A/2JR"JF<*+RR"JDZZ`6!81
  1203. M3RQX``0(+@`$`2EG%"\-2_H`"DZN_^(J7V`&0J?S7TYS2JR">&8P2JR"A&<HZ
  1204. M,"R"@DC`+P`O+(*$3KH!G#`L@H!20$C`Y8`O`"\L@GQ.N@&(3^\`$&`.3KH!8
  1205. M<B\L@GA.N@'06$\@+?_\+FR"8DYU*!].74YU3E4``$CG#B`X+0`(,`3!_``&I
  1206. M)$#5[()N2D1M"KAL@DYL!$J29A`Y?``"@I1P_TS?!'!.74YU""H`!P`$9@@OS
  1207. M$DZZ``I83T*2<`!@XB(O``0L;()J3N[_W"(O``0L;()J3N[_@B(O``0L;()JP
  1208. M3N[_N"QL@FI.[O_*+&R":D[N_WPB+P`$+&R":D[N_RA,[P`&``0L;()J3N[_W
  1209. MXBQL@FI.[O_$3OH``B(O``0L;()J3N[_IDSO``X`!"QL@FI.[O_02.<!!$SOT
  1210. M((``#"QL@F9.KO^43-\@@$YU(F\`!"QL@F9.[OX^3OH``B)O``0L;()F3N[^O
  1211. M8DSO`P``!"`O``PL;()F3N[]BB)O``0L;()F3N[^GB`O``0L;()F3N[^MD[ZZ
  1212. M``),[P`#``0L;()F3N[_.DCG`P`B;P`,+&R"9DZN_CA,WP#`3G5.^@`"(F\`#
  1213. M!"QL@F9.[O[:+&R"9D[N_WQ.^@`"(F\`!"`O``@L;()F3N[_+B`O``0L;()F!
  1214. M3N[^L"!O``0L;()F3N[^C"!O``1,[P(!``@B+P`0+&R"9D[N_D0L;()F(F\`,
  1215. M!"`O``A.[OW8(F\`!"QL@F9.[OZ8(F\`!"QL@F9.[OZ&3.\``P`$+&R"9D[NF
  1216. M_LX@;P`$+&R"9D[N_H!,[P,```0L;(*(3N[_H"!O``0L;(*(3N[_IB!O``0LM
  1217. M;(*(3N[_LDSO`P``!"QL@EY.[O_0```#[`````$````!```"&@````````/RJ
  1218. M```#Z@```)8P,3(S-#4V-S@Y86)C9&5F````("`@("`@("`@,#`P,#`@("`@U
  1219. M("`@("`@("`@("`@(""00$!`0$!`0$!`0$!`0$!`#`P,#`P,#`P,#$!`0$!`(
  1220. M0$`)"0D)"0D!`0$!`0$!`0$!`0$!`0$!`0$!`4!`0$!`0`H*"@H*"@("`@("0
  1221. M`@("`@("`@("`@("`@("0$!`0"```````````````````0`````!`````````
  1222. M``````````````$!`````0`````````````````````!`@````$`````````'
  1223. M`````````````````````````````````````````````````````````````
  1224. M`````````````````````````````````````````````````````````````
  1225. M`````````````````````````````````````````````````````````````
  1226. M`````````````````````````````````````````````````````````````
  1227. M`````````````````````````````````````````````````````````````
  1228. M`````````````````````````````````````````````````````````````
  1229. M`````````````````````````````````````````````````````````````
  1230. M`````````````````````````````````````````````````````````````
  1231. G````````````````%`````````````````/R```#ZP````$```/RM
  1232. ``
  1233. end
  1234. size 5484
  1235. SHAR_EOF
  1236. cat << \SHAR_EOF > SetCPU.uu
  1237.  
  1238. begin 644 SetCPU
  1239. M```#\P`````````#``````````(```<'````N`````$```/I```'!T[Z"V1([
  1240. MYP`,+'@`!`@N``(!*6<,(#P``0F^3-\P`$YU""X``0$I9B`(+@```2EF#"`\'
  1241. M``$)H$S?,`!.=2`\``$)JDS?,`!.=2`\``$)M$OZ``Q.KO_B3-\P`$YU3GH0T
  1242. M`BA!",$`!`B!``!.>Q`"3GH0`@@!``1G#"`\``$)O@CN``(!*2(,3GL0`DYS&
  1243. M+'@`!`@N``$!*68$<`!.=2\-2_H`"DZN_^(J7TYU3GH``DYS("\`!"QX``0(H
  1244. M+@`!`2EF`DYU+PU+^@`*3J[_XBI?3G5.>P`"3G,L>``$2.<`'")\`````$ZN1
  1245. M_MHF0"AK`#(G?````1P`,EF/\!="``Q```!G#@@N``(!*6<&(#P``0F^6(\GH
  1246. M3``R3-\X`$YU(!\,0``+9PP@/``!#/-8KP`"3G-P`%BO``).<R!O``0L>``$(
  1247. M+PU+^@`*3J[_XBI?3G7P$$X`3G,@;P`$+'@`!"\-2_H`"DZN_^(J7TYU\!!,^
  1248. M`$YS+'@`!"\-68\@3TOZ``Y.KO_B(!=8CRI?3G7P$$(`3G-![P`$+'@`!"\-Q
  1249. M2_H`"DZN_^(J7TYU\!!``$YS+PTL>``$""X`!`$I9@9P`"I?3G5+^@`*3J[_S
  1250. MXBI?3G4@/``!#1'S)W(`$B\``0Q!`!AG!B`\``$-$O-?3G,V.#`P,``V.#`QE
  1251. M,``V.#`R,``V.#`S,``V.#@U,0`V.#@X,0`V.#@X,@!&4%4`34U5`$Y5__X@V
  1252. M;0`(2A!G/"!M``Q*$&<T(&T`"%*M``@0$$B`P'P`WR!M``Q2K0`,$A!(@<)\L
  1253. M`-^P068(.WP``?_^8`1";?_^9P)@O"!M``A*$&8*2FW__F<$<`%@`G``3EU."
  1254. M=4Y5```,K0`!#1$`"&862'H`1DZZ#5!83TIL@"1G!$)L@#A@'@RM``$-$@`(2
  1255. M9A1(>@`M3KH-,%A/2FR`*F<$0FR`.$JM``AG"DIL@#!G!$)L@#A.74YU-C@X!
  1256. M.#$@`#8X.#@R(`!.5?_X0J<@+0`(T*T`#"\`3KH8?%!/*T#__&8&<`!.74YUT
  1257. M3KH8B"`M__S0K0`,4X`B+0`,4X%&@<"!*T#_^"`M``C0K0`,+P`O+?_\3KH8I
  1258. M:E!/+RW_^"\M``A.NA@"4$\K0/_\3KH8@B`M__Q@L$Y5_^A"K?_L0JW_Z$AX;
  1259. M$`!(>0`$``!.NO]Z4$\K0/_L2'@0`$AX`@!.NO]H4$\K0/_H2JW_[&<&2JW_"
  1260. MZ&8P2JW_Z&<.2'@"`"\M_^A.NA?\4$]*K?_L9Q!(>0`$```O+?_L3KH7YE!/9
  1261. M<`!.74YU2'D`!```+RW_[$AY`/P``$ZZ%XY/[P`,0JW__"`M__SE@"!M_^@B+
  1262. M+?_\=!'EH<*\____\`C!```A@0@`4JW__`RM````?O_\9=(@;?_H("W_[,"\<
  1263. M____\("\````!2%``?@@;?_H("W_[-"\``(``,"\____\("\````!2%``?PKU
  1264. M?`!_`@+_]"MM_^C_^$AM__1.NOT$6$\P+0`(P'P`#TC`<A#CH'(/DFT`",)\#
  1265. M``](P70,Y:&`@8"\@,`%`"M`__`O+?_P3KK]#%A/<`%@`/\L3E7_\$*M__1"O
  1266. MK?_P0J=.NOSR6$](;?_X3KK\D%A/*VW__/_P(&W_\"`H`?C`O/____`K0/_T/
  1267. M2'@"`"\M__!.NA;*4$](>0`$```O+?_T3KH6NE!/3EU.=4Y5_]@[?``!__Q"\
  1268. M;?_Z0JW_WCM\``C_V`QM``(`"&U"(&T`"B)H``0,$0`_9C1(>@3"2'H$GDZZ)
  1269. M"L)03TAZ!+E.N@JX6$](>@3@3KH*KEA/2'H%!DZZ"J183T)G3KH3Z%1/*WP`(
  1270. M``$!_^Y.NOLZ*T#_]@QM``$`"&\``D`[?``!_]Q@``(:#&P`!8`X9DY";?_:_
  1271. M<``P+?_<Y8`@;0`*+S`(`#`M_]K`_``&0>R``B\P"`!.NOR"4$]*0&<4,"W_?
  1272. MVL#\``9![(`&,;P``0@`8`Q2;?_:#&T`"?_:9;9(>@2K<``P+?_<Y8`@;0`*4
  1273. M+S`(`$ZZ_$103TI`9PHY?``%@#A@``&82'H$B7``,"W_W.6`(&T`"B\P"`!.<
  1274. MNOP<4$]*0&<*.WP``?_Z8``!<$AZ!&EP`#`M_]SE@"!M``HO,`@`3KK[]%!/^
  1275. M2D!G"CM\``+_^F```4A(>@1+<``P+?_<Y8`@;0`*+S`(`$ZZ^\Q03TI`9PA";
  1276. M;?_88``!(DAZ!"IP`#`M_]SE@"!M``HO,`@`3KK[IE!/2D!G"$)M__Q@``#\)
  1277. M2'H$#G``,"W_W.6`(&T`"B\P"`!.NON`4$]*0&<,*WP```$`_^Y@``#22'H#*
  1278. MZ7``,"W_W.6`(&T`"B\P"`!.NOM64$]*0&<,*WP````!_^Y@``"H2'H#Q'``_
  1279. M,"W_W.6`(&T`"B\P"`!.NOLL4$]*0&<*("W_[H&M__9@?DAZ`Z)P`#`M_]SE3
  1280. M@"!M``HO,`@`3KK[!%!/2D!G#"`M_^Y&@,&M__9@5$AZ`X!P`#`M_]SE@"!M7
  1281. M``HO,`@`3KKZVE!/2D!G#"`M_^[I@(&M__9@*DAZ`UQP`#`M_]SE@"!M``HOM
  1282. M,`@`3KKZL%!/2D!G#"`M_^[I@$:`P:W_]E)M_]PP+?_<L&T`"&4`_=X@+?_V+
  1283. M",``#2\`3KKY%%A/3KKX8BM`_^9.NOH"*T#_XDIM__QG3$ZZ^1XK0/_>9T).%
  1284. MNOFN"```'V8L#&T``?_Z9B(_+?_83KK[=E1/2D!F%$AZ`MI.N@?Z6$\_/``*+
  1285. M3KH1/%1/8`P,;0`"__IF!$ZZ_(Y(>@+I3KH'V%A/#*T``0FJ_^9B4@RM``$)8
  1286. MJO_F9A9(>@+43KH'NEA/2FR`#&<$0FR`.&`42'H"Q4ZZ!Z183TIL@`9G!$)L2
  1287. M@#@O+?_B3KKZ+%A/2'H"KDZZ!X983S\L@#A.NA#(5$\,K0`!";[_YF862'H"$
  1288. MDDZZ!VA83TIL@!AG!$)L@#A@%$AZ`H-.N@=26$]*;(`29P1";(`X+RW_XDZZP
  1289. M^=I83PRM``$,\__>9A1(>@)B3KH'*EA/2FR`'F<$0FR`.$JM_]YG"DIL@#9G-
  1290. M!$)L@#A*K?_>9Q1.NOB4"```'V<*2'H"-4ZZ!O983TZZ]YPK0/_V2'H"+$ZZ\
  1291. M!N183P@M``#_^68*2'H"(DZZ!M)83TAZ`AM.N@;(6$\,K0`!";[_YF9@2'H"G
  1292. M#4ZZ!K183P@M``3_^68*2'H!_4ZZ!J)83TAZ`?9.N@:86$\(+0``__AF#$AZ4
  1293. M`?-.N@:&6$]@"DAZ`?!.N@9Z6$\(+0`$__AF"DAZ`>5.N@9H6$](>@'>3KH&/
  1294. M7EA/2'H!VDZZ!E183RM\``$)OO_F9Q`@+?_V",``"R\`3KKW"EA//RR`.$ZZ5
  1295. M#WQ43TY=3G6;-VU3971#4%4@)7,@8GD@1&%V92!(87EN:66;,&T*`%8Q+C0`K
  1296. M57-A9V4Z(%-E=$-052!;24Y35'Q$051!72!;6TY/74-!0TA%?%M.3UU"55)3`
  1297. M5%T*`"`@("`@("`@("`@("`@6UM.3UU&05-44D]-(%M44D%075T@6TY/34U5Z
  1298. M5$535%T*`"`@("`@("`@("`@("`@6T-(14-+(#8X,'@P?#8X.#4Q?#8X.#AX@
  1299. M?$U-57Q&4%5="@!#2$5#2P!&05-44D]-`$Y/1D%35%)/30!44D%0`$Y/34U5O
  1300. M5$535`!$051!`$E.4U0`0T%#2$4`3D]#04-(10!"55)35`!.3T)54E-4`$5R1
  1301. M<F]R.B!#86XG="!G970@;65M;W)Y(&9O<B!&05-44D]-('1R86YS;&%T:6]NE
  1302. M"@!365-414TZ(``V.#`Q,"``-C@P,#`@``H`-C@P,S`@`#8X,#(P(``V.#@UL
  1303. M,2``1D%35%)/32``*$E.4U0Z(`!.3P!#04-(10`@`$Y/`$)54E-4*2`H1$%45
  1304. M03H@`$Y/0T%#2$4@`$-!0TA%(`!.3P!"55)35``I"@``87!#[(*21>R"DK7)7
  1305. M9@XR/``3:PAT`"+"4<G__"E/@I8L>``$*4Z"FDCG@(`(+@`$`2EG$$OZ``A.%
  1306. MKO_B8`9"I_-?3G-#^@`@3J[^:"E`@IYF#"X\``.`!TZN_Y1@!$ZZ`!I03TYU6
  1307. M9&]S+FQI8G)A<GD`2?D``'_^3G5.50``+PI(>0`!```P+(*&P?P`!B\`3KH/V
  1308. M>BE`@J)03V840J=(>0`!``!.N@\:4$\N;(*63G4@;(*B0F@`!"!L@J(Q?``!,
  1309. M`!`@;(*B,7P``0`*(&R"EB`L@I:0J``$4(`I0(*F(&R"IB"\34%.6$*G3KH/A
  1310. M+B1`2JH`K%A/9RXO+0`,+RT`""\*3KH`KCE\``&"JB!L@J(`:(````0@;(*B7
  1311. M`&B````*3^\`#&!"2&H`7$ZZ#UA(:@!<3KH/$BE`@JP@;(*L2J@`)%!/9Q`@O
  1312. M;(*L(F@`)"\13KH.!EA/+RR"K"\*3KH":"EL@JR"L%!/3KH.!B!L@J(@@$ZZ'
  1313. M#B8@;(*B(4``!F<62'@#[4AZ`"I.N@X"(&R"HB%```Q03R\L@K`_+(*T3KKWE
  1314. MX$)G3KH,(%!/)%].74YU*@!.50``2.<,,"1M`!`@;0`(2J@`K&<8(&T`""`HU
  1315. M`*SE@"@`($0@*``0Y8`F0&`$)FR"B!`32(!(P-"M``Q4@#E`@K9"IS`L@K9(&
  1316. MP"\`3KH.#"E`@KA03V8(3-\,,$Y=3G40$TB`.@`_!2!+4H@O""\L@KA.N@%^7
  1317. M,`5(P"!`T>R"N$/Z`400V6;\/RT`#B\*+RR"N$ZZ`3H@;(*X0C!0`#E\``&"L
  1318. MM#`%2,#0K(*X)D!2BR1+3^\`%!`32(`Z`+!\`"!G&+I\``EG$KI\``QG#+I\^
  1319. M``UG!KI\``IF!%*+8-@,$P`@;7H,$P`B9BY2BR!+4HL0$$B`.@!G'B!*4HH06
  1320. MA;I\`")F$`P3`")F!%*+8`9"*O__8`)@UF`X($M2BQ`02(`Z`&<FNGP`(&<@O
  1321. MNGP`"6<:NGP`#&<4NGP`#6<.NGP`"F<(($I2BA"%8,X@2E**0A!*168"4XM2L
  1322. M;(*T8`#_6D(20J<P+(*T4D!(P.6`+P!.N@SJ*4""L%!/9@A";(*T8`#^V'H`2
  1323. M)FR"N&`D,`5(P.6`(&R"L"&+"``@2R`(2AAF_)'`4X@P"%)`2,#7P%)%NFR"/
  1324. MM&W6,`5(P.6`(&R"L$*P"`!@`/Z4(``P/'__8`0P+P`,(&\`!$H89OQ32")O?
  1325. M``A30!#95\C__&<"0A`@+P`$3G5,[P,```0@"#(O``Q@`A#95\G__&<&4D%@,
  1326. M`D(84<G__$YU3E4``$CG#C`D;0`(0J=(>@".3KH,>"E`@KQ03V8(3-\,<$Y=H
  1327. M3G4@;0`,(F@`)"\I``1.N@RP*`!83V=22'H`;2!$+R@`-DZZ#((F0$J`4$]G>
  1328. M-$AX`^TO"TZZ"VPL`%!/9R0@!N6`*@`@125H``@`I"5&`)Q(>`/M2'H`.$ZZ_
  1329. M"T@E0`"@4$\O!$ZZ#$Y83R\L@KQ.N@N,0JR"O%A/8(!I8V]N+FQI8G)A<GD`J
  1330. M5TE.1$]7`"H`3E4``$AM``PO+0`(2'H$8$ZZ`)A/[P`,3EU.=4Y5``!(YP@@"
  1331. M)&T`#@QM``0`$F8((&T`""@08!Q*;0`,;PP@;0`(<``P$"@`8`H@;0`(,!!(7
  1332. MP"@`0FT`$DIM``QL$$1M``Q*A&P(1(0[?``!`!(R+0`,2,$@!$ZZ`Y!![(`Z3
  1333. M4XH4L```,BT`#$C!(`1.N@.&*`!FVDIM`!)G!E.*%+P`+2`*3-\$$$Y=3G5.G
  1334. M5?\B2.<(,"1M``@F;0`,0FW_^BMM`!#__"!+4HL0$$B`.`!G``+NN'P`)68`>
  1335. M`LQ"+?\P.WP``?_X.WP`(/_V.WPG$/_T($M2BQ`02(`X`+!\`"UF#D)M__@@#
  1336. M2U*+$!!(@#@`N'P`,&80.WP`,/_V($M2BQ`02(`X`+A\`"IF&"!M__Q4K?_\&
  1337. M.U#_\B!+4HL0$$B`.`!@,D)M__)@'#`M__+!_``*T$20?``P.T#_\B!+4HL0[
  1338. M$$B`.``P!%)`0>R`3`@P``(``&;4N'P`+F9:($M2BQ`02(`X`+!\`"IF&"!MN
  1339. M__Q4K?_\.U#_]"!+4HL0$$B`.`!@,D)M__1@'#`M__3!_``*T$20?``P.T#_N
  1340. M]"!+4HL0$$B`.``P!%)`0>R`3`@P``(``&;4.WP``O_PN'P`;&82($M2BQ`0W
  1341. M2(`X`#M\``3_\&`0N'P`:&8*($M2BQ`02(`X`#`$2,!@>CM\``C_[F`6.WP`]
  1342. M"O_N8`X[?``0_^Y@!CM\__;_[C\M__!(;?\P/RW_[B\M__Q.NOWD*T#_ZC`MA
  1343. M__!(P-&M__Q/[P`,8%P@;?_\6*W__")0*TG_ZB`)2AEF_)/`4XD[2?_P8$H@G
  1344. M;?_\5*W__#@00>W_+RM(_^H0A&`HD+P```!C9^)3@&>2D+P````+9P#_<EF`,
  1345. M9[)5@&<`_W!7@&<`_W)@S$'M_S"1[?_J.TC_\#`M__"P;?_T;P8[;?_T__!*Z
  1346. M;?_X9V@@;?_J#!``+6<*(&W_Z@P0`"MF+@QM`##_]F8F4VW_\B!M_^I2K?_JM
  1347. M$!!(@#\`3I*P?/__5$]F"G#_3-\,$$Y=3G5@%C\M__9.DK!\__]43V8$</]@E
  1348. MY%)M__HP+?_R4VW_\K!M__!NW$)M_^Y@("!M_^I2K?_J$!!(@#\`3I*P?/__<
  1349. M5$]F!'#_8+!2;?_N(&W_ZDH09PHP+?_NL&W_]&W.,"W_[M%M__I*;?_X9BA@K
  1350. M&#\\`"!.DK!\__]43V8&</]@`/]X4FW_^C`M__)3;?_RL&W_\&[:8!8_!$Z2V
  1351. ML'S__U1/9@9P_V``_U)2;?_Z8`#]"#`M__I@`/]"2.=(`$*$2H!J!$2`4D1*&
  1352. M@6H&1($*1``!83Y*1&<"1(!,WP`22H!.=4CG2`!"A$J`:@1$@%)$2H%J`D2!T
  1353. M81H@`6#8+P%A$B`!(A]*@$YU+P%A!B(?2H!.=4CG,`!(04I!9B!(038!-`!"Z
  1354. M0$A`@,,B`$A`,@*"PS`!0D%(04S?``Q.=4A!)@$B`$)!2$%(0$)`=`_0@-.!T
  1355. MMH%B!)*#4D!1RO_R3-\`#$YU3E4``$AL@.0_+0`(3KH`"%Q/3EU.=4Y5```OT
  1356. M!#@M``@O+0`*/P1.N@`PN'P`"EQ/9B0@;0`*$"@`#$B`"```!V<4/SS__R\M'
  1357. M``I.N@#T7$\H'TY=3G5@^$Y5```O"B1M``H@4K'J``1E&#`M``C`?`#_/P`O1
  1358. M"DZZ`,A<3R1?3EU.=2!24I(0+0`)$(!(@,!\`/]@Z$Y5```O"D'L@,XD2"!*:
  1359. MU?P````6+PAA$%A/0>R"AK7(9>HD7TY=3G5.50``2.<(("1M``AX`"`*9@IP]
  1360. M_TS?!!!.74YU2BH`#&=0""H``@`,9PP_//__+PIA4C@`7$\0*@`-2(`_`$ZZT
  1361. M!1R(0`@J``$`#%1/9PHO*@`(3KH"+EA/""H`!0`,9Q(O*@`23KH"P"\J`!).F
  1362. MN@(44$]"DD*J``1"J@`(0BH`##`$8)!.5?_^2.<(("1M``A!^O]&*4B"P`@JX
  1363. M``0`#&<*</],WP003EU.=0@J``(`#&<P(%*1Z@`(.`@_!"\J``@0*@`-2(`_;
  1364. M`$ZZ`H"P1%!/9Q`(Z@`$``Q"DD*J``1P_V#`#&W__P`,9A`(J@`"``Q"DD*JB
  1365. M``1P`&"H2JH`"&8(+PI.N@":6$\,:@`!`!!F*AMM``W__S\\``%(;?__$"H`[
  1366. M#4B`/P!.N@(BL'P``5!/9J`P+0`,8`#_:B2J``@P*@`02,#0J@`()4``!`CJI
  1367. M``(`#"!24I(0+0`-$(!(@,!\`/]@`/\^3E4``"\*0>R`SB1(2BH`#&<8U?P`Q
  1368. M```60>R"AK7(90AP`"1?3EU.=6#B0I)"J@`$0JH`""`*8.I.5?_\+PHD;0`(T
  1369. M/SP$`$ZZ`,`K0/_\5$]F\``$`$"!*T?P````.)4@`""1?3EU.=35\!```P
  1370. M$`CJ``$`#"5M__P`"!`J``U(@#\`3KH`XDI`5$]G!@`J`(``#&#.3E4``$CGL
  1371. M`#`D;(*28!0F4B`J``10@"\`+PI.N@1Z4$\D2R`*9NA"K(*23-\,`$Y=3G5.'
  1372. M50``+PI!^O_&*4B"Q$*G("T`"%"`+P!.N@0@)$!*@%!/9@AP`"1?3EU.=22L:
  1373. M@I(E;0`(``0I2H*2(`I0@&#F3E4``'``,"T`""\`8;)83TY=3G5.50``2.<`:
  1374. M,)?+)&R"DF`.(&T`"%&(L<IG$B9*)%(@"F;N</],WPP`3EU.=2`+9P0FDF`$P
  1375. M*5*"DB`J``10@"\`+PI.N@/,<`!03V#83E4``"\*,"T`",'\``8D0-7L@J)**
  1376. M;0`(;0XP+0`(L&R"AFP$2I)F#CE\``*"R'#_)%].74YU,"T`",'\``8@;(*BR
  1377. M+S`(`$ZZ`L9*@%A/9P1P`6`"<`!@V$Y5```O+0`(3KH"D$J`6$]F#DZZ`IHYQ
  1378. M0(+(</].74YU<`!@^$Y5``!(YPP@."T`"$ZZ`'`P!,'\``8D0-7L@J)*1&T*7
  1379. MN&R"AFP$2I)F$#E\``*"R'#_3-\$,$Y=3G4P*@`$P'P``V8*.7P`!8+(</]@+
  1380. MY'``,"T`#B\`+RT`"B\23KH"9BH`L+S_____3^\`#&8,3KH"&CE`@LAP_V"X!
  1381. M(`5@M$Y5__Q(>!``0J=.N@+^*T#__`@```Q03V<22FR"JF8(("W__$Y=3G5.^
  1382. MN@`&<`!@]$Y5``!(>``$2'H`'$ZZ`?`O`$ZZ`@(_/``!3KH`#D_O``Y.74YU)
  1383. M7D,*`$Y5``!*K(+`9P8@;(+`3I`_+0`(3KH`"%1/3EU.=4Y5__PO!#`M``A(R
  1384. MP"M`__Q*K(*B9RAX`&`*/P1.N@#^5$]21+AL@H9M\#`L@H;!_``&+P`O+(*B1
  1385. M3KH"&%!/2JR"Q&<&(&R"Q$Z02JR"C&<*+RR"C$ZZ`6A83TJL@LIG""!L@LH@Y
  1386. MK(+.2JR"TF<*+RR"TDZZ`9)83TJL@M9G"B\L@M9.N@&"6$]*K(+:9PHO+(+:&
  1387. M3KH!<EA/2JR"WF<*+RR"WDZZ`6)83RQX``0(+@`$`2EG%"\-2_H`"DZN_^(J/
  1388. M7V`&0J?S7TYS2JR"K&8P2JR"N&<H,"R"MDC`+P`O+(*X3KH!<#`L@K120$C`_
  1389. MY8`O`"\L@K!.N@%<3^\`$&`.3KH!1B\L@JQ.N@%^6$\@+?_\+FR"EDYU*!].:
  1390. M74YU3E4``$CG#B`X+0`(,`3!_``&)$#5[(*B2D1M"KAL@H9L!$J29A`Y?``"W
  1391. M@LAP_TS?!'!.74YU""H`!P`$9@@O$DZZ``I83T*2<`!@XB(O``0L;(*>3N[_Y
  1392. MW"(O``0L;(*>3N[_@B(O``0L;(*>3N[_N"QL@IY.[O_*+&R"GD[N_WPB+P`$G
  1393. M+&R"GD[N_RA,[P`&``0L;(*>3N[_XBQL@IY.[O_$3OH``B(O``0L;(*>3N[_^
  1394. MIDSO``X`!"QL@IY.[O_02.<!!$SO((``#"QL@II.KO^43-\@@$YU3.\"`0`$D
  1395. M+&R"FD[N_S1.^@`"(F\`!"QL@II.[OYB3.\#```$("\`#"QL@II.[OV*3OH`N
  1396. M`DSO``,`!"QL@II.[O\Z(F\`!"QL@II.[O[:3OH``BQL@II.[O]\3OH``B)O:
  1397. M``0@+P`(+&R"FD[N_RX@;P`$+&R"FD[N_HPL;(*:(F\`!"`O``A.[OW8+&R"0
  1398. MFD[N_W8B;P`$+&R"FD[N_H9,[P`#``0L;(*:3N[^SB!O``0L;(*:3N[^@$SO.
  1399. M`P``!"QL@KQ.[O^@(&\`!"QL@KQ.[O^F(&\`!"QL@KQ.[O^R```#[`````$`(
  1400. M````````\`````$````!```+V@````````/R```#Z@```*0```'J``````'PY
  1401. M``````'V``````'\``````("``````((``````(.``````(4``````(8````"
  1402. M`#`Q,C,T-38W.#EA8F-D968````@("`@("`@("`P,#`P,"`@("`@("`@("`@2
  1403. M("`@("`@()!`0$!`0$!`0$!`0$!`0$`,#`P,#`P,#`P,0$!`0$!`0`D)"0D)5
  1404. M"0$!`0$!`0$!`0$!`0$!`0$!`0$!0$!`0$!`"@H*"@H*`@("`@("`@("`@("Q
  1405. M`@("`@("`@)`0$!`(``````````````````!``````$`````````````````R
  1406. M`````0$````!``````````````````````$"`````0``````````````````'
  1407. M`````````````````````````````````````````````````````````````
  1408. M`````````````````````````````````````````````````````````````
  1409. M`````````````````````````````````````````````````````````````
  1410. M`````````````````````````````````````````````````````````````
  1411. M`````````````````````````````````````````````````````````````
  1412. M`````````````````````````````````````````````````````````````
  1413. M`````````````````````````````````````````````````````````````
  1414. M`````````````````````````````````````````````````````````````
  1415. M```````4`````````````````^P````)```````````````&````#````!(`P
  1416. G```8````'@```"0````J````,`````````/R```#ZP````$```/R-
  1417. ``
  1418. end
  1419. size 8004
  1420. SHAR_EOF
  1421. #    End of shell archive
  1422. exit 0
  1423. -- 
  1424. Bob Page, U of Lowell CS Dept.  page@swan.ulowell.edu  ulowell!page
  1425. Have five nice days.
  1426.